home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / Meshwriter / real.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  16.1 KB  |  528 lines

  1. /*
  2. **      $VER: real.c 1.00 (13.03.1999)
  3. **
  4. **      Creation date : 13.03.1999
  5. **
  6. **      Description       :
  7. **         Standart saver module for meshwriter.library.
  8. **         Saves the mesh as Real 3D object file.
  9. **
  10. **
  11. **      Written by Stephan Bielmann
  12. **
  13. */
  14.  
  15. /*************************** Includes *******************************/
  16.  
  17. /*
  18. ** Amiga includes
  19. */
  20.  
  21. #include <clib/dos_protos.h>
  22.  
  23. /*
  24. ** Project includes
  25. */
  26. #include "meshwriter_private.h"
  27. #include "utilities.h"
  28.  
  29. /**************************** Defines *******************************/
  30.  
  31. /*
  32. ** Number of elements in the buffers
  33. */
  34. #define Ci_BUFFERC 99    // color buffer must be dividable by 3 !
  35. #define Ci_BUFFERV 100    // vector buffer
  36. #define Ci_BUFFERE 100    // edge buffer must be dividable by 4 !
  37. #define Ci_BUFFERF 99    // face buffer must be dividable by 3 !
  38.  
  39. /*********************** Type definitions ***************************/
  40.  
  41. /*
  42. ** Private type definitions
  43. */
  44. typedef struct {
  45.     UBYTE platform[4];
  46.     LONG version;
  47.     LONG revision;
  48. }REALRvrs;
  49.  
  50.  
  51.  
  52.  
  53. typedef struct {
  54.     LONG x,y,z;
  55. } TDDDVector;
  56.  
  57. typedef struct {
  58.     UBYTE name[4];
  59.     ULONG size;
  60. } TDDDChunk;
  61.  
  62. typedef struct {
  63.     TDDDChunk chunk;
  64.     UBYTE oname[18];
  65. } TDDDNameChunk;
  66.  
  67. typedef struct {
  68.     TDDDChunk chunk;
  69.     UWORD shape;
  70.     UWORD lamp;
  71. } TDDDShapChunk;
  72.  
  73. typedef struct {
  74.     TDDDChunk chunk;
  75.     TDDDVector vector;
  76. } TDDDVectorChunk;
  77.  
  78. typedef struct {
  79.     TDDDChunk chunk;
  80.     TDDDVector xaxis,yaxis,zaxis;
  81. } TDDDAxisChunk;
  82.  
  83. typedef struct {
  84.     TDDDChunk chunk;
  85.     TDDDVector mins,maxs;
  86. } TDDDBBoxChunk;
  87.  
  88. typedef struct {
  89.     TDDDChunk chunk;
  90.     UWORD count;
  91. } TDDDCountChunk;
  92.  
  93. typedef struct {
  94.     TDDDChunk chunk;
  95.     ULONG count;
  96. } TDDDCountChunk2;
  97.  
  98. typedef struct {
  99.     TDDDChunk chunk;
  100.     UBYTE pad;
  101.     UBYTE r,g,b;
  102. } TDDDColorChunk;
  103.  
  104. /********************** Private functions ***************************/
  105.  
  106. /********************************************************************\
  107. *                                                                    *
  108. * Name         : float2long                                          *
  109. *                                                                    *
  110. * Description  : Converts a float value into an Imagine long value.  *
  111. *                                                                    *
  112. * Arguments    : f IN : The float value to convert.                  *
  113. *                                                                    *
  114. * Return Value : The converted value as LONG                         *
  115. *                                                                    *
  116. * Comment      :                                                     *
  117. *                                                                    *
  118. \********************************************************************/
  119. static LONG float2long(TOCLFloat f) {
  120.     if (f<0) return(-(LONG)(-65536.0*f+0.5));
  121.     else return((LONG)(65536.0*f+0.5));
  122. }
  123.  
  124. /********************** Public functions ****************************/
  125.  
  126. /********************************************************************\
  127. *                                                                    *
  128. * Name         : write3REAL                                          *
  129. *                                                                    *
  130. * Description  : Writes a standart Real 3D V2.20 binary file.        *
  131. *                                                                    *
  132. * Arguments    : realfile IN : An already opened file stream.        *
  133. *                mesh     IN : Pointer to the mesh.                  *
  134. *                                                                    *
  135. * Return Value : RCNOERROR                                           *
  136. *                RCWRITEDATA                                         *
  137. *                                                                    *
  138. * Comment      :                                                     *
  139. *                                                                    *
  140. \********************************************************************/
  141. ULONG write3REAL(BPTR realfile, TOCLMesh *mesh) {
  142.     TDDDChunk            form,obj,desc,tobj;
  143.     TDDDNameChunk        name;
  144.     TDDDAxisChunk        axis;
  145.     TDDDShapChunk        shap;
  146.     TDDDVectorChunk    posi,size;
  147.     TDDDBBoxChunk        bbox;
  148.     TDDDCountChunk        pnts,edge,face,clst,tlst;    
  149.     TDDDColorChunk        colr,refl,tran,spc1;
  150.     
  151.     TOCLPolygonNode            *pln=NULL;
  152.     TOCLPolygonsVerticesNode    *plvi=NULL,*plv1=NULL,*plv2=NULL,*plv3=NULL;
  153.     TOCLVertexNode                *ver=NULL;
  154.     TOCLMaterialNode            *mat=NULL;    
  155.  
  156.     TDDDVector            vbuffer[Ci_BUFFERV];    // Ci_BUFFERV * sizeof(TDDDVector)    vector buffer
  157.     UWORD                ebuffer[Ci_BUFFERE];    // Ci_BUFFERE * sizeof(UWORD)            edge buffer
  158.     UWORD                fbuffer[Ci_BUFFERF];    // Ci_BUFFERF * sizeof(UWORD)            face buffer
  159.     UBYTE                cbuffer[Ci_BUFFERC];    // Ci_BUFFERB                            byte buffer
  160.     ULONG                bufferstate;
  161.     ULONG                edgeoffset;
  162.  
  163. // werte check fract : -32767.5 bis 32767.5 => neuer rueckgabe wert !!
  164. // counts nicht groesser als 32k !!
  165.  
  166.     /*
  167.     ** Initializing all chunks and theyr sizes and static contents
  168.     */
  169.     setUBYTEArray(name.chunk.name,"NAME",4);
  170.     name.chunk.size = 18;     // fixed size
  171.     setUBYTEArray(name.oname,mesh->name,18);
  172.  
  173.     setUBYTEArray(shap.chunk.name,"SHAP",4);
  174.     shap.chunk.size=4;     // fixed size
  175.     shap.shape=2;            // an axis object
  176.     shap.lamp=0;            // not a lamp
  177.  
  178.     setUBYTEArray(posi.chunk.name,"POSI",4);
  179.     posi.chunk.size=12;                    // fixed size
  180.     posi.vector.x=float2long(0.0);        // origin of the object is fixed to {0,0,0}
  181.     posi.vector.y=float2long(0.0);
  182.     posi.vector.z=float2long(0.0);
  183.  
  184.     setUBYTEArray(axis.chunk.name,"AXIS",4);
  185.     axis.chunk.size=36;                            // fixed size
  186.     axis.xaxis.x=1,axis.xaxis.y=0,axis.xaxis.z=0;    // fixed x-axis unit vector
  187.     axis.yaxis.x=0,axis.yaxis.y=1,axis.yaxis.z=0;    // fixed y-axis unit vector
  188.     axis.zaxis.x=0,axis.zaxis.y=0,axis.zaxis.z=1;    // fixwd z-axis unit vector
  189.  
  190.     setUBYTEArray(size.chunk.name,"SIZE",4);
  191.     size.chunk.size=12;                                                // fixed size
  192.     size.vector.x=float2long(mesh->bBox.right - mesh->bBox.left);    // bbox length x axis
  193.     size.vector.y=float2long(mesh->bBox.front - mesh->bBox.rear);    // bbox length y axis
  194.     size.vector.z=float2long(mesh->bBox.top - mesh->bBox.bottom);    // bbox length z axis
  195.  
  196.     setUBYTEArray(bbox.chunk.name,"BBOX",4);
  197.     bbox.chunk.size=24;                            // fixed size
  198.     bbox.mins.x=float2long(mesh->bBox.left);        // bbox min x size
  199.     bbox.mins.y=float2long(mesh->bBox.rear);        // bbox min y size
  200.     bbox.mins.z=float2long(mesh->bBox.bottom);    // bbox min z size
  201.     bbox.maxs.x=float2long(mesh->bBox.right);        // bbox max x size
  202.     bbox.maxs.y=float2long(mesh->bBox.front);        // bbox max y size
  203.     bbox.maxs.z=float2long(mesh->bBox.top);        // bbox max z size
  204.  
  205.     setUBYTEArray(pnts.chunk.name,"PNTS",4);
  206.     // number of points = number of vertices
  207.     pnts.count=mesh->vertices.numberOfVertices;
  208.     pnts.chunk.size=sizeof(pnts.count) + pnts.count * sizeof(TDDDVector);    
  209.  
  210.     // number of faces = sum of each polygon (number of vertices - 2)
  211.     // number of edges = sum of each polygon ((number of vertices-3)*2 +3)
  212.     face.count=0;
  213.     edge.count=0;
  214.       if(mesh->polygons.firstNode!=NULL) {                 
  215.         pln=mesh->polygons.firstNode;
  216.         do {
  217.             // we accept only polygons with 3 or more points !
  218.             if (pln->numberOfVertices>=3) {
  219.                 face.count+=pln->numberOfVertices-2;
  220.                 edge.count+=(pln->numberOfVertices-3)*2+3;
  221.             }
  222.             pln=pln->next;
  223.         } while (pln!=NULL);
  224.     } 
  225.  
  226.     setUBYTEArray(face.chunk.name,"FACE",4);
  227.     face.chunk.size=sizeof(face.count) + face.count * 3 * sizeof(UWORD);
  228.     
  229.     setUBYTEArray(edge.chunk.name,"EDGE",4);
  230.     edge.chunk.size=sizeof(edge.count) + edge.count * 2 * sizeof(UWORD);
  231.  
  232.     setUBYTEArray(colr.chunk.name,"COLR",4);
  233.     colr.chunk.size=4;                    // fixed size
  234.     colr.pad=0;                        // default value
  235.     colr.r=255,colr.g=255,colr.b=255;    // default color is white
  236.  
  237.     setUBYTEArray(refl.chunk.name,"REFL",4);
  238.     refl.chunk.size=4;                        // fixed size
  239.     refl.pad=0;                            // default value
  240.     refl.r=0,colr.g=0,colr.b=0;            // default reflection is black
  241.  
  242.     setUBYTEArray(tran.chunk.name,"TRAN",4);
  243.     tran.chunk.size=4;                        // fixed size
  244.     tran.pad=0;                            // default value
  245.     tran.r=0,colr.g=0,colr.b=0;            // default transparency is none
  246.  
  247.     setUBYTEArray(spc1.chunk.name,"SPC2",4);
  248.     spc1.chunk.size=4;                    // fixed size
  249.     spc1.pad=0;                        // default value
  250.     spc1.r=255,colr.g=255,colr.b=255;    // default specularity is white
  251.  
  252.     setUBYTEArray(clst.chunk.name,"CLST",4);
  253.     // each face has its color so count = #faces
  254.     clst.count=face.count;
  255.     clst.chunk.size=sizeof(clst.count) + clst.count * 3 * sizeof(UBYTE);
  256.     // if an odd we have an odd count, size must be incremented to insert a pad
  257.     if (clst.count%2) clst.chunk.size++;
  258.  
  259.     setUBYTEArray(tlst.chunk.name,"TLST",4);
  260.     // each face has its transparency so count = #faces
  261.     tlst.count=face.count;
  262.     tlst.chunk.size=sizeof(tlst.count) + tlst.count * 3 * sizeof(UBYTE);
  263.     // if an odd we have an odd count, size must be incremented to insert a pad
  264.     if (tlst.count%2) tlst.chunk.size++;
  265.  
  266.     setUBYTEArray(desc.name,"DESC",4);
  267.     // size = sizes of all above and the size of themselves, = 8 Bytes each
  268.     // pnts,edge,face only if there are polygons and edges and faces
  269.     // clst,tlst only if there are materials and faces
  270.     
  271.     desc.size = name.chunk.size+axis.chunk.size+shap.chunk.size+posi.chunk.size+size.chunk.size;
  272.     desc.size += bbox.chunk.size+colr.chunk.size+refl.chunk.size+tran.chunk.size+spc1.chunk.size;
  273.     desc.size += 10 * 8;
  274.  
  275.     if(mesh->polygons.firstNode && edge.count && face.count) {
  276.         desc.size += pnts.chunk.size+edge.chunk.size+face.chunk.size;
  277.         desc.size += 3 * 8;
  278.     }
  279.     if(mesh->materials.firstNode && face.count) {
  280.         desc.size += clst.chunk.size+tlst.chunk.size;
  281.         desc.size += 2 * 8;
  282.     }
  283.  
  284.     setUBYTEArray(obj.name,"OBJ ",4);
  285.     // size = desc.size + 8 for desc itself and 8 for tobj
  286.     obj.size = desc.size + 16;
  287.  
  288.     setUBYTEArray(form.name,"FORM",4);
  289.     // size = obj.size + 8 for obj itself and 4 for tddd
  290.     form.size = obj.size + 12;
  291.  
  292.     setUBYTEArray(tobj.name,"TOBJ",4);
  293.     tobj.size=0;        // fixed size
  294.  
  295.  
  296.     /*
  297.     ** Writing the chunks and theyr dynamic content
  298.     */
  299.     if(FWrite(realfile,&form,sizeof(form),1)!=1) return(RCWRITEDATA);
  300.  
  301.     if(FWrite(realfile,"TDDD",1,4)!=4) return(RCWRITEDATA);
  302.     
  303.     if(FWrite(realfile,&obj,sizeof(obj),1)!=1) return(RCWRITEDATA);
  304.     
  305.     if(FWrite(realfile,&desc,sizeof(desc),1)!=1) return(RCWRITEDATA);
  306.  
  307.     if(FWrite(realfile,&name,sizeof(name),1)!=1) return(RCWRITEDATA);
  308.  
  309.     if(FWrite(realfile,&shap,sizeof(shap),1)!=1) return(RCWRITEDATA);
  310.  
  311.     if(FWrite(realfile,&posi,sizeof(posi),1)!=1) return(RCWRITEDATA);    
  312.  
  313.     if(FWrite(realfile,&axis,sizeof(axis),1)!=1) return(RCWRITEDATA);    
  314.  
  315.     if(FWrite(realfile,&size,sizeof(size),1)!=1) return(RCWRITEDATA);    
  316.     
  317.     if(FWrite(realfile,&bbox,sizeof(bbox),1)!=1) return(RCWRITEDATA);    
  318.  
  319.     // only if there are polygons to write, and edge and faces
  320.     if (mesh->polygons.firstNode && edge.count && face.count) {
  321.         if(FWrite(realfile,&pnts,sizeof(pnts),1)!=1) return(RCWRITEDATA);    
  322.  
  323.         // initialize the buffer state
  324.         bufferstate=0;
  325.  
  326.         // write the points
  327.         // this is a futil test but anyway
  328.         if(mesh->vertices.firstNode!=NULL) {
  329.             ver=mesh->vertices.firstNode;
  330.             do {
  331.                 TOCLVertex v=ver->vertex;
  332.  
  333.                 vbuffer[bufferstate].x=float2long(v.x);
  334.                 vbuffer[bufferstate].y=float2long(v.y);
  335.                 vbuffer[bufferstate].z=float2long(v.z);
  336.  
  337.                 // increment the bufferstate and 
  338.                 // check if the buffer is full and write and initialize it
  339.                 if (++bufferstate==Ci_BUFFERV) {
  340.                     if(FWrite(realfile,&vbuffer,Ci_BUFFERV*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  341.                     bufferstate=0;
  342.                 }
  343.                 
  344.                 ver=ver->next;
  345.             } while(ver!=NULL);
  346.         
  347.             // write the rest of the buffer if there is any
  348.             if (bufferstate!=0) {
  349.                 if(FWrite(realfile,&vbuffer,bufferstate*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  350.             }            
  351.         }
  352.  
  353.         if(FWrite(realfile,&edge,sizeof(edge),1)!=1) return(RCWRITEDATA);    
  354.     
  355.         // initialize the buffer state
  356.         bufferstate=0;
  357.  
  358.             pln=mesh->polygons.firstNode;
  359.         do {                                
  360.             // only if there are 3 or more points in the polygon
  361.             if(pln->numberOfVertices>=3) {
  362.                 plv1=pln->firstNode;
  363.             
  364.                 plvi=plv1;
  365.                 do {    
  366.                     plv2=plvi->next;
  367.                     plv3=plv2->next;
  368.                 
  369.                     ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  370.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  371.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  372.                     ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  373.  
  374.                     // check if the buffer is full and write and initialize it
  375.                     if (bufferstate==Ci_BUFFERE) {
  376.                         if(FWrite(realfile,&ebuffer,Ci_BUFFERE*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  377.                         bufferstate=0;
  378.                     }
  379.                 
  380.                     plvi=plvi->next;
  381.                 } while(plv3->next!=NULL);    
  382.                     
  383.                 ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  384.                 ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  385.  
  386.                 // write the rest of the buffer
  387.                 if(FWrite(realfile,&ebuffer,bufferstate*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  388.                 bufferstate=0;
  389.             }
  390.             pln=pln->next;
  391.         } while(pln!=NULL);
  392.         
  393.         if(FWrite(realfile,&face,sizeof(face),1)!=1) return(RCWRITEDATA);    
  394.  
  395.         // initialize the buffer state
  396.         bufferstate=0;
  397.  
  398.         // initialize the edge offset
  399.         edgeoffset=0;
  400.  
  401.         pln=mesh->polygons.firstNode;
  402.         do {                                
  403.             ULONG i;
  404.             
  405.             // only if there are 3 or more points in the polygon
  406.             if(pln->numberOfVertices>=3) {
  407.                   // do this for each edge - 1
  408.                 for(i=0;i<((pln->numberOfVertices-3)*2+2);i+=2) {
  409.                     fbuffer[bufferstate++]=edgeoffset+i;
  410.                     fbuffer[bufferstate++]=edgeoffset+i+1;
  411.                     fbuffer[bufferstate++]=edgeoffset+i+2;
  412.                     
  413.                     // check if the buffer is full and write and initialize it
  414.                     if (bufferstate==Ci_BUFFERF) {
  415.                         if(FWrite(realfile,&fbuffer,Ci_BUFFERF*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  416.                         bufferstate=0;
  417.                     }
  418.                 }
  419.                 edgeoffset+=i+1;
  420.             }
  421.             pln=pln->next;
  422.         } while(pln!=NULL);
  423.  
  424.         // write he rest of the buffer if there is any
  425.         if (bufferstate!=0) {
  426.             if(FWrite(realfile,&fbuffer,bufferstate*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  427.             bufferstate=0;
  428.         }
  429.     }
  430.     
  431.     if(FWrite(realfile,&colr,sizeof(colr),1)!=1) return(RCWRITEDATA);
  432.  
  433.     if(FWrite(realfile,&refl,sizeof(refl),1)!=1) return(RCWRITEDATA);
  434.  
  435.     if(FWrite(realfile,&tran,sizeof(tran),1)!=1) return(RCWRITEDATA);
  436.     
  437.     if(FWrite(realfile,&spc1,sizeof(spc1),1)!=1) return(RCWRITEDATA);
  438.     
  439.     // writing the materials if there are some, and if there are any faces
  440.     if(mesh->materials.firstNode && face.count) {
  441.         if(FWrite(realfile,&clst,sizeof(clst),1)!=1) return(RCWRITEDATA);          
  442.  
  443.         // initialize the buffer state
  444.         bufferstate=0;
  445.  
  446.         // The ambient color, per face
  447.         pln=mesh->polygons.firstNode;
  448.         do {
  449.             TOCLColor col=pln->materialNode->ambientColor;
  450.  
  451.             // we accept only polygons with 3 or more points !
  452.             if (pln->numberOfVertices>=3) {
  453.                 ULONG i;
  454.                 
  455.                 for(i=0;i<(pln->numberOfVertices-2);i++) {
  456.                     cbuffer[bufferstate++]=col.r;
  457.                     cbuffer[bufferstate++]=col.g;
  458.                     cbuffer[bufferstate++]=col.b;
  459.  
  460.                     // check if the buffer is full and write and initialize it
  461.                     if (bufferstate==Ci_BUFFERC) {
  462.                         if(FWrite(realfile,&cbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  463.                         bufferstate=0;
  464.                     }
  465.                 }
  466.             }
  467.                         
  468.             pln=pln->next;
  469.         } while(pln!=NULL);
  470.  
  471.         // if we have an odd count a pad has to be added at the end
  472.         if (clst.count%2) {
  473.             cbuffer[bufferstate++]=0;
  474.         }
  475.         
  476.         // write the rest of the buffer if any
  477.         if (bufferstate!=0) {
  478.             if(FWrite(realfile,&cbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  479.             bufferstate=0;
  480.         }
  481.  
  482.         if(FWrite(realfile,&tlst,sizeof(tlst),1)!=1) return(RCWRITEDATA);          
  483.  
  484.         // initialize the buffer state
  485.         bufferstate=0;
  486.  
  487.         // The transparency, per face
  488.         pln=mesh->polygons.firstNode;
  489.         do {
  490.             // we accept only polygons with 3 or more points !
  491.             if (pln->numberOfVertices>=3) {
  492.                 ULONG i;
  493.                 
  494.                 for(i=0;i<(pln->numberOfVertices-2);i++) {  
  495.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  496.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  497.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  498.  
  499.                     // check if the buffer is full and write and initialize it
  500.                     if (bufferstate==Ci_BUFFERC) {
  501.                         if(FWrite(realfile,&cbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  502.                         bufferstate=0;
  503.                     }
  504.                 }
  505.             }
  506.             
  507.             pln=pln->next;
  508.         } while(pln!=NULL);
  509.  
  510.         // if we have an odd count a pad has to be added at the end
  511.         if (tlst.count%2) {
  512.             cbuffer[bufferstate++]=0;
  513.         }
  514.         
  515.         // write the rest of the buffer if any
  516.         if (bufferstate!=0) {
  517.             if(FWrite(realfile,&cbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  518.             bufferstate=0;
  519.         }
  520.     }
  521.  
  522.     if(FWrite(realfile,&tobj,sizeof(tobj),1)!=1) return(RCWRITEDATA);
  523.   
  524.     return(RCNOERROR);
  525. }
  526.  
  527. /************************* End of file ******************************/
  528.